using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Admin.NET.Application.Entity;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Application.Excel;
using Admin.NET.Application.Service.Report.Dto;
using Admin.NET.Core;
using Furion;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;

namespace Admin.NET.Application.Service.Report;

public class EnergyRank : IDynamicApiController, ITransient, IPrivateDependency
{
	private readonly SqlSugarRepository<PowerConsumptionRecord> _rep;

	private readonly SqlSugarRepository<Building> _repQuery;

	public EnergyRank(SqlSugarRepository<PowerConsumptionRecord> rep, SqlSugarRepository<Building> repQuery)
	{
		_rep = rep;
		_repQuery = repQuery;
	}

	[HttpPost("/report/getenergyrank")]
	public async Task<List<EnergyRankReport>> GetEnergyRank([FromBody] EnergyRankInput input)
	{
		List<EnergyRankReport> building;
		List<long> listid;
		if (input.Type == 0)
		{
			building = await (from u in _repQuery.Context.Queryable<Building>()
				select new EnergyRankReport
				{
					Id = u.Id,
					BuildingName = u.Name
				}).ToListAsync();
			listid = building.Select((EnergyRankReport u) => u.Id).ToList();
			if (listid.Count > 0)
			{
				var info = await (from u in _rep.Context.Queryable<PowerConsumptionRecord>()
					where u.CreateTime >= input.StartTime && u.CreateTime <= input.EndTime && listid.Contains(u.BuildingId.Value)
					group u by new { u.BuildingId } into u
					select new
					{
						buildingId = u.BuildingId,
						allCount = SqlFunc.AggregateSum(u.CombinedActiveTotalElectricEnergyDifference)
					}).ToListAsync();
				building.ForEach(delegate(EnergyRankReport u)
				{
					u.AllPower = Math.Round(info.Where(s => s.buildingId == u.Id).Sum(a => a.allCount), 2);
				});
			}
			BuildingData(building);
			return building.OrderBy((EnergyRankReport u) => u.Index).ToList();
		}
		if (input.Type == 1)
		{
			building = await _repQuery.Context.Queryable((Room x, Building y) => new JoinQueryInfos(JoinType.Left, x.BuildingId == y.Id)).Select((Room x, Building y) => new EnergyRankReport
			{
				Id = x.Id,
				RoomName = x.Name,
				BuildingName = y.Name
			}).ToListAsync();
			listid = building.Select((EnergyRankReport u) => u.Id).ToList();
			if (listid.Count > 0)
			{
				var info = await (from u in _rep.Context.Queryable<PowerConsumptionRecord>()
					where u.CreateTime >= input.StartTime && u.CreateTime <= input.EndTime && listid.Contains(u.RoomId.Value)
					group u by new { u.RoomId } into u
					select new
					{
						roomId = u.RoomId,
						allCount = SqlFunc.AggregateSum(u.CombinedActiveTotalElectricEnergyDifference)
					}).ToListAsync();
				building.ForEach(delegate(EnergyRankReport u)
				{
					u.AllPower = Math.Round(info.Where(s => s.roomId == u.Id).Sum(a => a.allCount), 2);
				});
			}
			BuildingData(building);
			return building.OrderBy((EnergyRankReport u) => u.Index).ToList();
		}
		building = await _repQuery.Context.Queryable((ElectricMeter x, Room y, Building z) => new JoinQueryInfos(JoinType.Left, x.RoomId == (long?)y.Id, JoinType.Left, y.BuildingId == z.Id)).Select((ElectricMeter x, Room y, Building z) => new EnergyRankReport
		{
			Id = x.Id,
			Name = x.Name,
			Sn = x.Sn,
			RoomName = y.Name,
			BuildingName = z.Name
		}).ToListAsync();
		listid = building.Select((EnergyRankReport u) => u.Id).ToList();
		if (listid.Count > 0)
		{
			var info = await (from u in _rep.Context.Queryable<PowerConsumptionRecord>()
				where u.CreateTime >= input.StartTime && u.CreateTime <= input.EndTime && listid.Contains(u.MeterId)
				group u by new { u.MeterId } into u
				select new
				{
					meterId = u.MeterId,
					allCount = SqlFunc.AggregateSum(u.CombinedActiveTotalElectricEnergyDifference)
				}).ToListAsync();
			_ = info;
			building.ForEach(delegate(EnergyRankReport u)
			{
				u.AllPower = Math.Round(info.Where(s => s.meterId == u.Id).Sum(a => a.allCount), 2);
			});
		}
		BuildingData(building);
		return building.OrderBy((EnergyRankReport u) => u.Index).ToList();
	}

	private void BuildingData(List<EnergyRankReport> building)
	{
		building = building.OrderByDescending((EnergyRankReport u) => u.AllPower).ToList();
		int index = 1;
		decimal lastValue = -1m;
		int count = 0;
		building.ForEach(delegate(EnergyRankReport u)
		{
			if (lastValue == -1m)
			{
				u.Index = index;
			}
			else
			{
				if (lastValue == u.AllPower)
				{
					count++;
				}
				else
				{
					index = index + 1 + count;
					count = 0;
				}
				u.Index = index;
			}
			lastValue = u.AllPower;
		});
	}

	[HttpPost("/report/energyrankexecl")]
	public async Task<IActionResult> ExportQuaryrank([FromBody] EnergyRankInput input)
	{
		List<EnergyRankReport> list = await GetEnergyRank(input);
		string str = "能耗排名统计-" + DateTime.Now.ToString("yyyy-MM-dd");
		List<string> column = new List<string>();
		List<string> title = new List<string>();
		string titleEx = "能耗排名-" + input.StartTime.Date.ToString("yyyy-MM-dd") + "-" + input.EndTime.Date.ToString("yyyy-MM-dd");
		if (input.Type == 0)
		{
			column.AddRange(new string[4] { "Index", "BuildingName", "AllPower", "AddCo2" });
			title.AddRange(new string[4] { "名次", "区域名称", "总能耗（kW.h）", "碳排放（kg）" });
		}
		else if (input.Type == 1)
		{
			column.AddRange(new string[5] { "Index", "RoomName", "BuildingName", "AllPower", "AddCo2" });
			title.AddRange(new string[5] { "名次", "房间名称", "所属区域", "总能耗（kW.h）", "碳排放（kg）" });
		}
		else
		{
			column.AddRange(new string[7] { "Index", "Sn", "Name", "BuildingName", "RoomName", "AllPower", "AddCo2" });
			title.AddRange(new string[7] { "名次", "表编号", "表名称", "所属区域", "所属房间", "总能耗（kW.h）", "碳排放（kg）" });
		}
		MemoryStream memery = ExportToExcel.ExportToList(list.ToArray(), titleEx, titleEx, column.ToArray(), title.ToArray());
		App.HttpContext.Response.ContentType = "application/vnd.ms-excel";
		byte[] aa = memery.ToArray();
		return new FileStreamResult(new MemoryStream(aa), "application/octet-stream")
		{
			FileDownloadName = str + ".xlsx"
		};
	}
}
